#ifndef ObjArray_First
#define ObjArray_First
#ifdef __GNUG__
#pragma interface
#endif

#include "SeqColl.h"

class ObjArrayIter;
class OrdCollection;

extern const char
	*cOutOfBoundsError,
	*cMethodName;

//---- ObjArray ----------------------------------------------------------------

class ObjArray: public SeqCollection {
friend ObjArrayIter;
friend OrdCollection;
public:
	MetaDef(ObjArray);

	//---- creation, destruction
	ObjArray(int s= cContainerInitCap, int lowerBound= 0);
	~ObjArray();
	void InitNew();
	void Expand(int);	// expand or shrink an array
	Object *Add(Object*);
	int Index(Object*);
	void FreeAll();

	//---- accessing
	Iterator *MakeIterator(bool dir= cIterForward, void *placement= 0);
	int IndexOfPtr(Object*);	// return -1 if not found
	int IndexOf(Object*);	//        "           "
	Object *At(int i);
	Object *AtPut(int i, Object *op);
	void AtPutAndExpand(int i, Object *op);	// expand the array if necessary
	Object *&operator[](int i);
	Object *UncheckedAt(int i);
	Object *RemoveAt(int i);
	Object *Remove(Object*);
	Object *RemovePtr(Object*);
	int LowerBound()
		{ return lb; }
	void Sort(int upto= cMaxInt);
	int BinarySearch(Object*, int upto= cMaxInt);
		// the ObjArray has to be sorted, -1 == not found !!

	//---- comparing
	u_long Hash();
	bool IsEqual(Object*);
	int Compare(Object*);

	//---- activation/passivation
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
	
private:
	bool BoundsOk(char *where, int at);

	Object **cont;
	int lb;	// lower bound of the array
};

//---- ObjArrayIter ------------------------------------------------------------

class ObjArrayIter: public Iterator {
public:
	ObjArrayIter(ObjArray *s);
	~ObjArrayIter();

	void Reset();
	Object *operator()();
	virtual bool Filter(Object*);
private:
	int ce;
	ObjArray *cs;
};

//---- inlines -----------------------------------------------------------------

inline bool ObjArray::BoundsOk(char *where, int at)
{
	if (at < lb || at-lb >= Size()) {
		Error(where, cOutOfBoundsError, at, Size(), this);
		return FALSE;
	} else
		return TRUE;
}
		
inline Object*& ObjArray::operator[](int at)
{
	if (at < lb || at-lb >= size)
		Error(cMethodName, cOutOfBoundsError, at, size, this);
	return cont[at-lb];
}

inline Object *ObjArray::UncheckedAt(int i)
	{ return cont[i]; }

#endif

